// call
// 使用一个指定的this值和单独给出的一个或多个参数来调用一个函数
Function.prototype.sx_call = function (obj, ...args) {
    obj = obj || window;
    // Symbol 是唯一的，防止重名key
    const fn = Symbol();
    obj[fn] = this;
    // 执行，返回执行值
    return obj[fn](...args);
}

const testobj = {
    name: 'Anzia',
    testFn(age) {
        console.log(`${this.name}${age}岁了`);
    }
}

const testobj2 = {
    name: 'HarmonyOS'
}

testobj.testFn.sx_call(testobj2, 3);
// HarmonyOS3岁了

// apply
// 调用一个具有给定this值的函数，以及以一个数组（或类数组对象）的形式提供的参数
Function.prototype.sx_apply = function (obj, args) {
    obj = obj || window;
    // Symbol是唯一的，防止重名key
    const fn = Symbol();
    obj[fn] = this;
    // 执行，返回执行值
    return obj[fn](...args);
}

testobj.testFn.sx_apply(testobj2, [2]);
// HarmonyOS2岁了

// bind
// bind返回一个函数，而不是执行结果
Function.prototype.sx_bind = function (obj, ...args) {
    obj = obj || window;

    // Symbol是唯一值，防止重名key
    const fn = Symbol();
    obj[fn] = this;
    const _this = this;

    const res = function (...innerArgs) {
        console.log(this, _this);
        if (this instanceof _this) {
            this[fn] = _this;
            this[fn](...[...args, ...innerArgs]);
            delete this[fn];
        } else {
            obj[fn](...[...args, ...innerArgs]);
            delete obj[fn];
        }
    }

    res.prototype = Object.create(this.prototype);
    return res;
}